#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   SaveJson
@Time    :   2023/03/26 20:53:04
@author  :   Eval
@Version :   1.0
@Describe:   封装一个将json数据有序写入json文件的方法, 保证二维数组的格式不混乱
'''

def __useDict(info:dict):
	# 属于更下一级的子元素, 缩进需要再进一步
	indent = 8
	kInfo = "{"
	infoTmp = info
	waiIn = 0
	for d in info:
		kInfo += "\n"+" "*indent+f'"{d}": '
		# 判断字典里面的数据是否是数组
		if type(info[d]) == list:
			arrTmp = info[d]
			infoTmp = "["
			lIndex = 0
			for ci in arrTmp:
				if type(ci) == dict:
					# infoTmp += __logicDict(ci)
					cTmp = "\n"+" "*(indent+4)+"{"
					for cindex,cDict in enumerate(ci):
						if type(ci[cDict]) == str:
							ci[cDict] =  ci[cDict] .replace("\n","\\n")
							cTmp += f"\"{cDict}\": \"{ci[cDict]}\""
							
						if type(ci[cDict]) == bool:
							ci[cDict] = "true" if ci[cDict] else "false"
							cTmp += f"\"{cDict}\": {ci[cDict]}"
							
						if type(ci[cDict]) == list:
							cTmp += f"\"{cDict}\": {__useList(ci[cDict])}"

						if cindex != len(ci) -1:
							cTmp += ","

					if lIndex == len(arrTmp) -1:
						cTmp += "}\n"+" "*indent
					else:
						cTmp += "},"
					
					infoTmp += cTmp
				else:
					# 判断是否到了迭代的末尾, 末尾的数据就不用加 逗号和换行了
					if lIndex == len(arrTmp) -1:
						infoTmp += f"{ci}"
					else:
						infoTmp += f"{ci},"
					# infoTmp += "]"
				# 遍历位置+1
				lIndex += 1

			if waiIn == len(info.keys()) -1:
				infoTmp += "]"
			else:
				infoTmp += "],"

			kInfo += infoTmp
		elif type(info[d]) == dict:
			kInfo = __logicDict(info)
		else:
			# 只将类型原本就是str的用双引号包裹,
			if type(info[d]) == str:
				if waiIn == len(info.keys()) -1:
					kInfo += f'"{info[d]}"'
				else:
					kInfo += f'"{info[d]}",'
			else:
				if waiIn == len(info.keys()) -1:
					kInfo += str(info[d])
				else:
					kInfo += f'{info[d]},'
			
		waiIn += 1
	indent = 4
	kInfo += "\n"+" "*indent+"}"
	return kInfo

def __logicDict(info:dict,indent=8):
	# 单独处理字典类型的数据
	kInfo = "{\n"
	for index,d in enumerate(info):
		# 如果子项还是字典, 那么再次递归
		if type(info[d]) == dict:
			kInfo += " "*indent+f'"{d}": {__logicDict(info[d],indent=indent+4)}'
			
			if index == len(info) -1:
				kInfo += "\n"+" "*indent+"}"
			else:
				kInfo += "\n"+" "*indent+"},\n"
		elif type(info[d]) == list:
			kInfo += " "*indent+f'"{d}": {__useList(info[d],indent=indent)}'

		elif type(info[d]) == bool:
			info[d] = "true" if info[d] else "false"
			if index == len(info) -1:
				kInfo += " "*indent+f'"{d}": {info[d]}'
			else:
				kInfo += " "*indent+f'"{d}": {info[d]},\n'
		else:
			if index == len(info) -1:
				kInfo += " "*indent+f'"{d}": "{info[d]}"'
			else:
				kInfo += " "*indent+f'"{d}": "{info[d]}",\n'
			
	return kInfo

def __useList(info:list,indent = 4):
	"""
	params: info  需要处理的列表
	判断数组的第一个元素是否是 二维数组,这里只实现 二维数组的方法, 一维数组直接写入, 其他多维的数组方法同理
	实现的功能是保存 用二维数组渲染的游戏地图, 所以子元素的类型都一致,只用判断一个就行
	"""
	result = str(info)
	# 给末尾添加的额外元素
	endStr = ",\n"
	if type(info[0]) == list:
		result = "[\n"
		lIndex = 0
		for ci in info:
			# 判断是否到了迭代的末尾, 末尾的数据就不用加 逗号和换行了
			if lIndex == len(info) -1:
				endStr = ""
			# 内容的缩进需要比 [] 括号多一格
			result += " "*(indent+4)+f"{ci}{endStr}"
			# 遍历位置+1
			lIndex += 1
			
		result += "\n"+" "*indent+"]"
	else:
		infoTmp = "["
		lIndex = 0
		for ci in info:
			if type(ci) == dict:
				infoTmp += "\n"+" "*(indent+4)+__logicDict(ci,indent+8)
				if lIndex == len(info) -1:
					infoTmp += "\n"+" "*(indent+4)+"}"
				else:
					infoTmp += "\n"+" "*(indent+4)+"},"
			else:
				# 判断是否到了迭代的末尾, 末尾的数据就不用加 逗号和换行了, 
				if type(ci) == str:
					if lIndex == len(info) -1:
						infoTmp += f'"{ci}"'
					else:
						infoTmp += f'"{ci}",'
				else:
					# 如果类型是整形, 那么不加双引号
					if lIndex == len(info) -1:
						infoTmp += f"{ci}"
					else:
						infoTmp += f'{ci},'
			# 遍历位置+1
			lIndex += 1
		infoTmp += "]"
		result = infoTmp
	return result

def save(json:dict):
	"""对外开放的方法"""
	res = "{\n"
	# 缩进
	indent = 4
	# 当前的遍历的位置
	index = 0
	# 当前字典(json数据) 的可迭代长度
	keyLen = len(json.keys())

	for i in json:
		# 得到当前值
		info = json[i]
		# 获取到当前值的类型
		dataTp = type(info)
		# 给末尾添加的额外元素
		endStr = ",\n"
		# 如果当前值是数组, 需要特殊处理
		if dataTp == list and len(info):
			info = __useList(info)

		# 处理字典
		if dataTp == dict and info.keys():
			info = __useDict(info)

		# 如果当前行的类型是str那么就需要使用双引号
		if dataTp == str:
			info = f'"{info}"'
		if dataTp == bool:
			if info:
				info = "false"
			else:
				info = "false"
				
		if index == keyLen -1:
			endStr = ""
		# 将当前行的最终数据追加到res
		res += " "*indent+f'"{i}": {info}{endStr}'
		index += 1

	res += "\n}"
	return res


# a = {
#     "0": {"type": "terrains", "index": 0, "rect": [32, 32], "animMax": 0, "key": "0", "id": "ea292ed3-9be6-4a98-b8e1-017b2434fa35", "name": "地板", "doorInfo": ""},
#    "4": {"type": "animates", "index": 2, "rect": [32, 32], "animMax": 4, "key": "4"},
#     "5": {"type": "npcs", "index": 9, "rect": [32, 32], "animMax": 2, "key": [
# 			{
# 				"type": "playSound",
# 				"name": "dialogue.mp3"
# 			},
# 			{
# 				"type": "speakTip",
# 				"msg": "勇敢的去吧!!勇士",
# 				"data": ["仙子", "fairy"]
# 			},
# 			{
# 				"type": "hide",
# 				"loc": [10, 7],
# 				"floorId": "",
# 				"remove": "true"
# 			}
# 		]},
	
# 	"FloorFiles": ["入口", "MT_0", "MT_1", "MT_2"],
# 	"MapImages": [
# 		{
# 			"name": "terrains.png",
# 			"anim": 0
# 		},
# 		{
# 			"name": "animates.png",
# 			"anim": 4
# 		}
# 	]
# }
# a["MapImages"][0]["anim"] = True
# a["5"]["key"][2]["remove"] = True
# # print(a)
# with open("data.json", "w",encoding="utf8") as f:
# 	f.write(save(a))
